package com.googlecode.dgwt.client.dojo.data.base;

import java.util.Collection;
import java.util.List;
import java.util.Set;

import com.googlecode.dgwt.client.dojo.callback.SimpleCallback;
import com.googlecode.dgwt.client.dojo.callback.VoidCallback;
import com.googlecode.dgwt.client.dojo.data.listener.AttachListener;
import com.googlecode.dgwt.client.dojo.data.listener.DataListener;
import com.googlecode.dgwt.client.dojo.data.listener.TransactionListener;

/**
 * @author wellsantos@wellsantos.com
 * @since 0.01
 */
public interface Store<Item> extends Collection<Item> {

    public Store<Item> append(Item item);
    
    /**
     *  FIXME se hover dois item iguais
     *        pode ser que modifique a linha errada.
     * 
     * @param curItem
     * @param newItem
     * @return True if the item was successful replaced
     */
    public boolean replace(Item curItem, Item newItem);
    
    public Item findByValues(Object ...columnValues);
    
    public Item findByValues(int startColumnIndex, Object ...columnValues); 
    
    /**
     * A read-only store can only be read. <br>
     * Trying to add, remove or set value will fail.
     * 
     * @return True if this store can't be written
     */
    public boolean isReadOnly();

    
    public Object getValue(Item item, int columnIndex);
    public boolean setValue(Item item, int columnIndex, Object value);

    
    public void refresh();
    public void refreshItem(Item item);
    public void refreshValue(Item item, int columnIndex);

    /**
     * Notifies that an item is modified. <br/>
     * This method does not update the item fields on widgets. 
     * It's used only to notify {@link TransactionListener TransactionListeners}. <br/>
     * To refresh data on screen call {@link #refreshItem(Object)}.
     * 
     * @param item
     *            the item that has been changed
     * @return True if this store contains the item
     */
    public boolean modified(Item item);
    
    /**
     * Loads into Store the specified amount of elements
     * @param index initial index to fetch
     * @param count amount of elements
     * @param callback called when loading finishs
     */
    public void fetch(int index, int count, VoidCallback callback);
    
    
    /**
     * Loads into Store the specified amount of elements
     * @param index initial index to fetch
     * @param count amount of elements
     * @param callback called when loading finishs (with the requested elements) 
     */
    public void fetch(int index, int count, SimpleCallback<List<Item>> callback);

    
    public boolean addListener(DataListener<Item> listener);
    
    public boolean removeListener(AttachListener<?> listener);
    
    public boolean hasListener(AttachListener<?> listener);
    
    public Set<DataListener<Item>> getDataListeners();
    
    
    /**
     * Cria um novo store espelhado no store atual
     * @return um store que compartilha os mesmos items e listeners
     */
    public Store<Item> createMirror();

    public Store<Item> cloneStore();

    /**
     * A store should be considered equals to another one one if they are the
     * same instance.
     * 
     * @param o
     *            an object
     */
    public boolean equals(Object o);

    /**
     * For stores, hash code should be equals the result by calling
     * {@link System#identityHashCode(Object)}.
     * 
     * @return the hash code for this store
     */
    public int hashCode();
    
}
